package com.jingfang.cloud.core;

import com.fazecast.jSerialComm.SerialPort;
import com.jingfang.cloud.MzContext;
import com.jingfang.cloud.constant.enums.Command;
import com.jingfang.cloud.core.event.SerialPortConnectEvent;
import com.jingfang.cloud.core.event.StartCommandEvent;
import com.jingfang.cloud.core.event.StopCommandEvent;
import lombok.Getter;
import lombok.extern.slf4j.Slf4j;
import org.dromara.quickswing.QSApplication;
import org.dromara.quickswing.events.QSEvent;
import org.dromara.quickswing.events.QSEventListener;

import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;

@Slf4j
@Getter
public class SerialPortService implements Runnable {
    private final SerialPort serialPort;
    private final MzContext context;
    private Thread thread;
    private Boolean run = true;
    private String filePath;


    public SerialPortService(MzContext context, String portName) {
        this.serialPort = SerialPort.getCommPort(portName);
        this.serialPort.setBaudRate(115200);
        this.serialPort.setNumDataBits(8);
        this.serialPort.setParity(SerialPort.NO_PARITY);
        this.serialPort.setNumStopBits(SerialPort.ONE_STOP_BIT);
        this.serialPort.setComPortTimeouts(SerialPort.TIMEOUT_READ_BLOCKING, 0, 0);
        this.context = context;
        context.getEventBus().subscribe(new QSEventListener<QSApplication>() {
            @Override
            protected void onEvent(QSEvent qsEvent) {
                if (qsEvent instanceof StartCommandEvent) {
                    StartCommandEvent startCommandEvent = (StartCommandEvent) qsEvent;
                    start((String) startCommandEvent.getMessage(), startCommandEvent.getCommand());
                }
                if (qsEvent instanceof StopCommandEvent) {
                    stop();
                }
            }
        });
    }

    public Boolean openSerialPort() {
        return serialPort.openPort();
    }

    private void start(String filePath, Command command) {
        this.sendCommand(command);
        this.filePath = filePath;
        if (this.thread == null) {
            this.thread = new Thread(this);
            this.thread.start();
        }
    }

    private void stop() {
        int i = this.sendCommand(Command.STOP);
        log.info("发送停止命令: {}", i);
        if (this.thread != null) {
            this.thread.interrupt();
            this.thread = null;
        }
    }

    public int sendCommand(Command command) {
        return this.serialPort.writeBytes(command.getCommand().getBytes(), command.getCommand().getBytes().length);
    }

    @Override
    public void run() {
        try (InputStream inputStream = serialPort.getInputStream()) {
            while (run) {
                byte[] buffer = new byte[258];
                int bytesRead = inputStream.read(buffer);
                if (bytesRead > 0) {
                    try (FileOutputStream fos = new FileOutputStream(filePath, true)) {
                        log.info("读取到数据: {}", new String(buffer, 0, bytesRead));
                        log.info("写入文件: {}", filePath);
                        fos.write(buffer);
                    }
                } else {
                    run = false;
                }
            }
        } catch (IOException e) {
            log.error("读取串口数据时发生错误: {}", e.getMessage());
            context.getEventBus().publish(new SerialPortConnectEvent(e));
        }
    }
}
